﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using LexicalAnalysisCs;

namespace AsmFromGpp
{
    public class GenerateAsm
    {
        private string m_AsmCode = "";
        private string m_FileName = "";
        private List<LexicalAnalyzerCs.StrInt> m_AsmInstList;
        private List<LexicalAnalyzerCs.StrInt> m_AsmOperandList;

        public string MAsmCode
        {
            get { return m_AsmCode; }
        }

        public string GenAsmToFile(string inFileName)
        {
            m_FileName = inFileName;
            Process exeFile = new Process();
            exeFile.StartInfo.FileName = "g++";
            exeFile.StartInfo.Arguments = "-O3 -o " + inFileName + ".asm -S " + inFileName;
            exeFile.StartInfo.CreateNoWindow = true;
            exeFile.StartInfo.UseShellExecute = false;
            exeFile.StartInfo.RedirectStandardOutput = true;

            try
            {
                exeFile.Start();
                exeFile.WaitForExit();
                exeFile.Close();

                return "";              // empty string means succeed in this function;
            } catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                return ex.Message;
            }
        }

        public List<LexicalAnalyzerCs.StrInt> MAsmInstList
        {
            get { return m_AsmInstList; }
        }

        public List<LexicalAnalyzerCs.StrInt> MAsmOperandList
        {
            get { return m_AsmOperandList; }
        }

        public void GenInstructionList()
        {
            m_AsmInstList = new List<LexicalAnalyzerCs.StrInt>();
            m_AsmOperandList = new List<LexicalAnalyzerCs.StrInt>();
            FileStream fs = new FileStream(m_FileName + ".asm", FileMode.Open);
            StreamReader sr = new StreamReader(fs);
            string tmp = "";
            StringBuilder asmCode = new StringBuilder();
            int cnt = 0;

            while (!sr.EndOfStream)
            {
                tmp = sr.ReadLine();
                if (tmp == "_main:")
                {
                    m_AsmInstList.Add(new LexicalAnalyzerCs.StrInt(tmp, cnt + tmp.Length + 1));
                    cnt += tmp.Length + 1;
                    asmCode.Append(tmp + "\n");
                    break;
                }
            }

            while (!sr.EndOfStream)
            {
                tmp = sr.ReadLine();
                if (tmp[0] == '\t' || tmp[0] == ' ')
                {
                    StringBuilder sb = new StringBuilder(10);
                    for (int i = 1; i < tmp.Length; i++)
                    {
                        if (tmp[i] == ' ' || tmp[i] == '\t')
                        {
                            string[] txp = tmp.Substring(i + 1, tmp.Length - i - 1).Split(',');
                            int ct = cnt + sb.ToString().Length + 1;
                            for (int j = 0; j < txp.Length; j++)
                            {
                                ct += txp[j].Length;
                                m_AsmOperandList.Add(new LexicalAnalyzerCs.StrInt(txp[j].Trim(), ct + 1));
                                ct += 1;
                            }
                            break;
                        }
                        sb.Append(tmp[i]);
                    }
                    m_AsmInstList.Add(new LexicalAnalyzerCs.StrInt(sb.ToString(), cnt + sb.ToString().Length + 1));
                }
                asmCode.Append(tmp + "\n");
                cnt += tmp.Length + 1;

                if (tmp.Contains("__GLOBAL__"))     // End of asm main func
                {
                    break;
                }
            }
            m_AsmCode = asmCode.ToString();

            sr.Close();
            fs.Close();
        }

    }
}
